package com.csw.android.dev_utils.log

import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Color
import android.graphics.Point
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.csw.android.dev_utils.R
import com.csw.android.dev_utils.databinding.DevUtilsFragmentLogViewBinding
import com.csw.android.dev_utils.log.request.RequestLogDialog
import com.csw.android.dev_utils.log.request.RequestLogInfo
import com.csw.android.dev_utils.ui.FragmentViewProperty
import com.csw.android.dev_utils.ui.databinding.DataBindingFragment
import com.csw.android.dev_utils.utils.RxBus
import com.csw.android.dev_utils.utils.SpaceLineDecoration
import com.csw.android.dev_utils.utils.ToastUtils
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.Disposable

class LogViewFragment : DataBindingFragment<DevUtilsFragmentLogViewBinding>() {
    companion object {
        /**
         * 悬浮窗在容器中的偏移量
         */
        val floatWindowOffset = MutableLiveData<Point?>()

        init {
            floatWindowOffset.observeForever {
                LogOperation.saveFloatWindowOffset(it)
            }
            floatWindowOffset.value = LogOperation.getFloatWindowOffset()
        }
    }

    private val logInfoList = ArrayList<LogInfo>()
    private var logAdapter: LogAdapter? by FragmentViewProperty {}
    private var onNewLogInfoListener: Disposable? by FragmentViewProperty { it?.dispose() }
    private var onLogExpandChangedListener: Disposable? by FragmentViewProperty { it?.dispose() }
    private var onBackPressedCallback: OnBackPressedCallback? by FragmentViewProperty { it?.remove() }
    private var autoEnd = true

    override fun getContentViewID() = R.layout.dev_utils_fragment_log_view

    override fun initView(rootView: View, savedInstanceState: Bundle?) {
        super.initView(rootView, savedInstanceState)
        dataBinding?.run {
            logListView.run {
                layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
                addItemDecoration(SpaceLineDecoration(0, 0, 0, 1, Color.TRANSPARENT))
                logAdapter = LogAdapter(logInfoList)
                adapter = logAdapter
                addOnScrollListener(object : RecyclerView.OnScrollListener() {
                    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                        super.onScrollStateChanged(recyclerView, newState)
                        when (newState) {
                            RecyclerView.SCROLL_STATE_IDLE -> {
                                layoutManager?.let { lm ->
                                    if (lm is LinearLayoutManager) {
                                        val lastItem =
                                            lm.findLastCompletelyVisibleItemPosition()
                                        val lastItem2 = lm.findLastVisibleItemPosition()
                                        if (lastItem >= 0 && lastItem == logInfoList.size - 1) {
                                            autoEnd = true
                                        } else if (lastItem == -1 && lastItem2 >= 0 && lastItem2 == logInfoList.size - 1) {
                                            autoEnd = true
                                        }
                                    }
                                }
                            }

                            RecyclerView.SCROLL_STATE_DRAGGING -> {
                                autoEnd = false
                            }
                        }
                    }
                })
            }
            floatWindowLayout.run {
                onWindowOffsetUpdate = { x, y ->
                    floatWindowOffset.postValue(Point(x, y))
                }
                setOnClickListener {
                    LogDisplayController.instance.onLogExpandChanged(logListView.visibility == View.GONE)
                }
            }
        }
    }

    override fun initListener() {
        super.initListener()
        //悬浮按钮位置
        floatWindowOffset.observe(viewLifecycleOwner) {
            dataBinding?.floatWindowLayout?.run {
                translationX = (it?.x ?: 0).toFloat()
                translationY = (it?.y ?: 0).toFloat()
            }
        }
        //返回按键处理
        onBackPressedCallback = object : OnBackPressedCallback(false) {
            init {
                activity?.onBackPressedDispatcher?.addCallback(this)
            }

            override fun handleOnBackPressed() {
                LogDisplayController.instance.onLogExpandChanged(false)
            }
        }
        //列表数据
        logInfoList.clear()
        onNewLogInfoListener?.dispose()
        onNewLogInfoListener = RxBus.getDefault().toObservable(OnNewLogInfo::class.java)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                if (logInfoList.contains(it.logInfo)) {
                    return@subscribe
                }
                logInfoList.add(it.logInfo)
                logAdapter?.notifyItemInserted(logInfoList.size - 1)
                dataBinding?.logListView?.run {
                    if (autoEnd) {
                        post {
                            val dest = logInfoList.size - 1
                            if (dest >= 0) {
                                smoothScrollToPosition(dest)
                            }
                        }
                    }
                }
            }
        //展开状态
        onLogExpandChangedListener?.dispose()
        setExpandState(LogDisplayController.instance.logExpanded)
        onLogExpandChangedListener = RxBus.getDefault().toObservable(OnLogExpandChanged::class.java)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                setExpandState(it.expand)
            }

    }

    private fun setExpandState(expand: Boolean) {
        onBackPressedCallback?.isEnabled = expand
        dataBinding?.run {
            logListView.run {
                if (expand) {
                    val dest = logInfoList.size - 1
                    if (dest >= 0) {
                        post {
                            scrollToPosition(dest)
                        }
                    }
                    visibility = View.VISIBLE
                    logIcon.setImageResource(R.drawable.dev_utils_svg_ic_logs_enable)
                } else {
                    visibility = View.GONE
                    logIcon.setImageResource(R.drawable.dev_utils_svg_ic_logs_disable)
                }
            }
        }
    }

    override fun onResume() {
        super.onResume()
        LogDisplayController.instance.getLogList().apply {
            logInfoList.clear()
            logInfoList.addAll(this)
            logAdapter?.notifyDataSetChanged()
            dataBinding?.logListView?.run {
                val dest = logInfoList.size - 1
                if (dest >= 0) {
                    post {
                        scrollToPosition(dest)
                    }
                }
            }
        }
    }

    private inner class LogAdapter(data: ArrayList<LogInfo>) :
        BaseQuickAdapter<LogInfo, BaseViewHolder>(
            R.layout.dev_utils_item_log, data
        ) {

        init {
            setOnItemClickListener { _, view, position ->
                getItem(position).let { item ->
                    when (item) {
                        is RequestLogInfo -> {
                            RequestLogDialog(view.context, item).show()
                        }

                        else -> {
                            (view.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).run {
                                setPrimaryClip(ClipData.newPlainText("LogInfo", item.toString()))
                                ToastUtils.showShort("已复制到剪贴板")
                            }
                        }
                    }
                }
            }
//            setOnItemLongClickListener { _, view, position ->
//                getItem(position).let { item ->
//                    (view.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).run {
//                        setPrimaryClip(ClipData.newPlainText("LogInfo", item.toString()))
//                        ToastUtils.showShort("已复制到剪贴板")
//                    }
//                }
//                return@setOnItemLongClickListener true
//            }
        }

        override fun convert(holder: BaseViewHolder, item: LogInfo) {
            val color = when (item.level) {
                Log.VERBOSE -> Color.GRAY
                Log.DEBUG -> Color.CYAN
                Log.INFO -> Color.BLACK
                Log.WARN -> Color.BLUE
                Log.ERROR -> Color.RED
                else -> {
                    Color.BLACK
                }
            }
            holder.setTextColor(R.id.tv_time, color)
            holder.setTextColor(R.id.tv_log, color)
            holder.setText(R.id.tv_time, item.getTime())
            holder.setText(R.id.tv_log, item.getContent())
        }
    }
}